/* main.c - Application main entry point */

/*
 * Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"

#include "esp_log.h"
#include "nvs_flash.h"

#include "esp_ble_mesh_defs.h"
#include "esp_ble_mesh_common_api.h"
#include "esp_ble_mesh_provisioning_api.h"
#include "esp_ble_mesh_networking_api.h"
#include "esp_ble_mesh_config_model_api.h"
#include "esp_ble_mesh_generic_model_api.h"

#include "ble_mesh_example_init.h"
#include "my_dev_init.h"
#include "my_json_parse.h" 
#include "my_mqtt.h"
#include "my_dev_info.h"



#define TAG "ESP32_BLE_MESH"

static void HexToString(char *str, uint8_t *hex, int nLen);
static int AsciiToHex(const char *pAscStr,uint8_t *pHexStr,int Len); 


#define LED_OFF             0x0
#define LED_ON              0x1

#define CID_ESP             0x8888

#define PROV_OWN_ADDR       0x0001

#define MSG_SEND_TTL        3
#define MSG_SEND_REL        false
#define MSG_TIMEOUT         0
#define MSG_ROLE            ROLE_PROVISIONER

#define COMP_DATA_PAGE_0    0x00

#define APP_KEY_IDX         0x0000
#define APP_KEY_OCTET       0x12

static uint8_t dev_uuid[16];
uint8_t node_mac[12] = {0};     //临时存放节点MAC地址

#define ESP_BLE_MESH_VND_MODEL_ID_CLIENT    0x0000
#define ESP_BLE_MESH_VND_MODEL_ID_SERVER    0x0001

#define MSG_TIMEOUT         0
#define MSG_ROLE            ROLE_PROVISIONER

//自定义Vendor 模型
#define ESP_BLE_MESH_VND_MODEL_OP_TEST_PERF_GET                 ESP_BLE_MESH_MODEL_OP_3(0xD0, 0x8888)
#define ESP_BLE_MESH_VND_MODEL_OP_TEST_PERF_SET                 ESP_BLE_MESH_MODEL_OP_3(0xD1, 0x8888)
#define ESP_BLE_MESH_VND_MODEL_OP_TEST_PERF_SET_UNACK           ESP_BLE_MESH_MODEL_OP_3(0xD2, 0x8888)
#define ESP_BLE_MESH_VND_MODEL_OP_TEST_PERF_STATUS              ESP_BLE_MESH_MODEL_OP_3(0xD3, 0x8888)

typedef struct {
    uint8_t  uuid[16];
    uint16_t unicast;
    uint8_t  elem_num;
    uint8_t  onoff;
    uint8_t node_mac[13];
} esp_ble_mesh_node_info_t;

static esp_ble_mesh_node_info_t nodes[CONFIG_BLE_MESH_MAX_PROV_NODES] = {
    [0 ... (CONFIG_BLE_MESH_MAX_PROV_NODES - 1)] = {
        .unicast = ESP_BLE_MESH_ADDR_UNASSIGNED,
        .elem_num = 0,
        .onoff = LED_OFF,
    }
};

static struct esp_ble_mesh_key {
    uint16_t net_idx;
    uint16_t app_idx;
    uint8_t  app_key[16];
} prov_key;

static esp_ble_mesh_client_t config_client;



static esp_ble_mesh_cfg_srv_t config_server = {
    .beacon = ESP_BLE_MESH_BEACON_DISABLED,
#if defined(CONFIG_BLE_MESH_FRIEND)
    .friend_state = ESP_BLE_MESH_FRIEND_ENABLED,
#else
    .friend_state = ESP_BLE_MESH_FRIEND_NOT_SUPPORTED,
#endif
    .default_ttl = 7,
    /* 3 transmissions with 20ms interval */
    .net_transmit = ESP_BLE_MESH_TRANSMIT(2, 20),
    .relay_retransmit = ESP_BLE_MESH_TRANSMIT(2, 20),
};

static esp_ble_mesh_model_t root_models[] = {
    ESP_BLE_MESH_MODEL_CFG_SRV(&config_server),
    ESP_BLE_MESH_MODEL_CFG_CLI(&config_client),
};



static const esp_ble_mesh_client_op_pair_t vnd_op_pair[] = {
    { ESP_BLE_MESH_VND_MODEL_OP_TEST_PERF_SET,      ESP_BLE_MESH_VND_MODEL_OP_TEST_PERF_STATUS },
    { ESP_BLE_MESH_VND_MODEL_OP_TEST_PERF_GET,      ESP_BLE_MESH_VND_MODEL_OP_TEST_PERF_STATUS },
    { ESP_BLE_MESH_VND_MODEL_OP_TEST_PERF_SET_UNACK,ESP_BLE_MESH_VND_MODEL_OP_TEST_PERF_STATUS },
};

esp_ble_mesh_client_t vendor_client = {
    .op_pair_size = ARRAY_SIZE(vnd_op_pair),
    .op_pair = vnd_op_pair,
};

esp_ble_mesh_model_op_t vnd_op[] = {
    ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_VND_MODEL_OP_TEST_PERF_GET,       1),
    ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_VND_MODEL_OP_TEST_PERF_SET,       1),
    ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_VND_MODEL_OP_TEST_PERF_SET_UNACK, 1),
    ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_VND_MODEL_OP_TEST_PERF_STATUS,    1),
    ESP_BLE_MESH_MODEL_OP_END,
};

//供应商模型
static esp_ble_mesh_model_t vnd_models[] = {
    ESP_BLE_MESH_VENDOR_MODEL(CID_ESP, ESP_BLE_MESH_VND_MODEL_ID_CLIENT,
    vnd_op, NULL, &vendor_client),
};





static esp_ble_mesh_elem_t elements[] = {
    // ESP_BLE_MESH_ELEMENT(0, root_models, ESP_BLE_MESH_MODEL_NONE),
    ESP_BLE_MESH_ELEMENT(0, root_models, vnd_models),
};

static esp_ble_mesh_comp_t composition = {
    .cid = CID_ESP,         //公司标识符
    .elements = elements,   //元素
    .element_count = ARRAY_SIZE(elements),
};

static esp_ble_mesh_prov_t provision = {
    .prov_uuid           = dev_uuid,        //预配器设备uuid
    .prov_unicast_addr   = PROV_OWN_ADDR,   //预配器主要元素的地址
    .prov_start_address  = 0x0005,          //节点启始地址     
    .prov_attention      = 0x00,
    .prov_algorithm      = 0x00,
    .prov_pub_key_oob    = 0x00,
    .prov_static_oob_val = NULL,
    .prov_static_oob_len = 0x00,
    .flags               = 0x00,
    .iv_index            = 0x00,
};

static esp_err_t example_ble_mesh_store_node_info(const uint8_t uuid[16], uint16_t unicast,
                                                  uint8_t elem_num, uint8_t onoff_state, uint8_t mac[12])
{
    int i;
    if (!uuid || !ESP_BLE_MESH_ADDR_IS_UNICAST(unicast)) {
        return ESP_ERR_INVALID_ARG;
    }

    /* Judge if the device has been provisioned before */
    for (i = 0; i < ARRAY_SIZE(nodes); i++) {
        if (!memcmp(nodes[i].uuid, uuid, 16)) {
 
            ESP_LOGW(TAG, "%s: reprovisioned device 0x%04x", __func__, unicast);
            nodes[i].unicast = unicast;
            nodes[i].elem_num = elem_num;
            nodes[i].onoff = onoff_state;

            // printf("### %04x - %04x - %04x\n",nodes[i].unicast,nodes[i].elem_num,nodes[i].onoff);
            return ESP_OK;
        }
    }

    for (i = 0; i < ARRAY_SIZE(nodes); i++) {
        if (nodes[i].unicast == ESP_BLE_MESH_ADDR_UNASSIGNED) {
            memcpy(nodes[i].uuid, uuid, 16);
            nodes[i].unicast = unicast;
            nodes[i].elem_num = elem_num;
            nodes[i].onoff = onoff_state;
            memcpy(nodes[i].node_mac, mac, 12);
            // printf("%04x - %04x - %04x - %s\n",nodes[i].unicast,nodes[i].elem_num,nodes[i].onoff, nodes[i].node_mac);
            return ESP_OK;
        }
    }

    return ESP_FAIL;
}

static esp_ble_mesh_node_info_t *example_ble_mesh_get_node_info(uint16_t unicast)
{
    int i;

    if (!ESP_BLE_MESH_ADDR_IS_UNICAST(unicast)) {
        return NULL;
    }

    for (i = 0; i < ARRAY_SIZE(nodes); i++) {
        if (nodes[i].unicast <= unicast &&
                nodes[i].unicast + nodes[i].elem_num > unicast) {
            return &nodes[i];
        }
    }

    return NULL;
}

static esp_err_t example_ble_mesh_set_msg_common(esp_ble_mesh_client_common_param_t *common,
                                                 esp_ble_mesh_node_info_t *node,
                                                 esp_ble_mesh_model_t *model, uint32_t opcode)
{
    if (!common || !node || !model) {
        return ESP_ERR_INVALID_ARG;
    }

    common->opcode = opcode;
    common->model = model;
    common->ctx.net_idx = prov_key.net_idx;
    common->ctx.app_idx = prov_key.app_idx;
    common->ctx.addr = node->unicast;
    common->ctx.send_ttl = MSG_SEND_TTL;
    common->ctx.send_rel = MSG_SEND_REL;
    common->msg_timeout = MSG_TIMEOUT;
    common->msg_role = MSG_ROLE;

    return ESP_OK;
}

static esp_err_t prov_complete(int node_idx, const esp_ble_mesh_octet16_t uuid,
                               uint16_t unicast, uint8_t elem_num, uint16_t net_idx, uint8_t mac[12])
{
    esp_ble_mesh_client_common_param_t common = {0};
    esp_ble_mesh_cfg_client_get_state_t get_state = {0};
    esp_ble_mesh_node_info_t *node = NULL;
    char name[11] = {0};
    int err;

    ESP_LOGI(TAG, "node index: 0x%x, unicast address: 0x%02x, element num: %d, netkey index: 0x%02x",
             node_idx, unicast, elem_num, net_idx);
    ESP_LOGI(TAG, "device uuid: %s", bt_hex(uuid, 16));

    sprintf(name, "%s%d", "NODE-", node_idx);
    //设置节点名字
    err = esp_ble_mesh_provisioner_set_node_name(node_idx, name);
    if (err) {
        ESP_LOGE(TAG, "%s: Set node name failed", __func__);
        return ESP_FAIL;
    }
    //保存节点信息
    err = example_ble_mesh_store_node_info(uuid, unicast, elem_num, LED_OFF, mac);
    if (err) {
        ESP_LOGE(TAG, "%s: Store node info failed", __func__);
        return ESP_FAIL;
    }

    node = example_ble_mesh_get_node_info(unicast);
    if (!node) {
        ESP_LOGE(TAG, "%s: Get node info failed", __func__);
        return ESP_FAIL;
    }

    example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET);
    get_state.comp_data_get.page = COMP_DATA_PAGE_0;
    err = esp_ble_mesh_config_client_get_state(&common, &get_state);
    if (err) {
        ESP_LOGE(TAG, "%s: Send config comp data get failed", __func__);
        return ESP_FAIL;
    }

    return ESP_OK;
}



static void prov_link_open(esp_ble_mesh_prov_bearer_t bearer)
{
    ESP_LOGI(TAG, "%s link open", bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT");
}

static void prov_link_close(esp_ble_mesh_prov_bearer_t bearer, uint8_t reason)
{
    ESP_LOGI(TAG, "%s link close, reason 0x%02x",
             bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT", reason);
}

//addr:为节点的MAC地址
static void recv_unprov_adv_pkt(uint8_t dev_uuid[16], uint8_t addr[BD_ADDR_LEN],
                                esp_ble_mesh_addr_type_t addr_type, uint16_t oob_info,
                                uint8_t adv_type, esp_ble_mesh_prov_bearer_t bearer)
{
    esp_ble_mesh_unprov_dev_add_t add_dev = {0};
    int err;

    /* Due to the API esp_ble_mesh_provisioner_set_dev_uuid_match, Provisioner will only
     * use this callback to report the devices, whose device UUID starts with 0xdd & 0xdd,
     * to the application layer.
     */

    ESP_LOGI(TAG, "address: %s, address type: %d, adv type: %d", bt_hex(addr, BD_ADDR_LEN), addr_type, adv_type);
    ESP_LOGI(TAG, "device uuid: %s", bt_hex(dev_uuid, 16));
    ESP_LOGI(TAG, "oob info: %d, bearer: %s", oob_info, (bearer & ESP_BLE_MESH_PROV_ADV) ? "PB-ADV" : "PB-GATT");

    // memset(node_mac, 0, sizeof(node_mac));
    // memcpy(node_mac, bt_hex(addr, BD_ADDR_LEN), strlen(bt_hex(addr, BD_ADDR_LEN)));
    // printf("len = %d, mac = %s\r\n", strlen(bt_hex(addr, BD_ADDR_LEN)), node_mac);
    // printf("mac len = %d\r\n", strlen(node_mac));
    memcpy(add_dev.addr, addr, BD_ADDR_LEN);
    add_dev.addr_type = (uint8_t)addr_type;
    memcpy(add_dev.uuid, dev_uuid, 16);
    add_dev.oob_info = oob_info;
    add_dev.bearer = (uint8_t)bearer;
    /* Note: If unprovisioned device adv packets have not been received, we should not add
             device with ADD_DEV_START_PROV_NOW_FLAG set. */
    err = esp_ble_mesh_provisioner_add_unprov_dev(&add_dev,
            ADD_DEV_RM_AFTER_PROV_FLAG | ADD_DEV_START_PROV_NOW_FLAG | ADD_DEV_FLUSHABLE_DEV_FLAG);
    if (err) {
        ESP_LOGE(TAG, "%s: Add unprovisioned device into queue failed", __func__);
    }

    return;
}

static void example_ble_mesh_provisioning_cb(esp_ble_mesh_prov_cb_event_t event,
                                             esp_ble_mesh_prov_cb_param_t *param)
{
    switch (event) {    
    case ESP_BLE_MESH_PROVISIONER_PROV_ENABLE_COMP_EVT:     //预配器启用预配功能完成事件
        ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_PROV_ENABLE_COMP_EVT, err_code %d", param->provisioner_prov_enable_comp.err_code);
        break;
    case ESP_BLE_MESH_PROVISIONER_PROV_DISABLE_COMP_EVT:    //预配器禁用预配功能完成事件
        ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_PROV_DISABLE_COMP_EVT, err_code %d", param->provisioner_prov_disable_comp.err_code);
        break;
    case ESP_BLE_MESH_PROVISIONER_RECV_UNPROV_ADV_PKT_EVT:  //预配器收到未配置的设备信标事件
        ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_RECV_UNPROV_ADV_PKT_EVT");
        memset(node_mac, 0, sizeof(node_mac));
        memcpy(node_mac, bt_hex(param->provisioner_recv_unprov_adv_pkt.addr, BD_ADDR_LEN), strlen(bt_hex(param->provisioner_recv_unprov_adv_pkt.addr, BD_ADDR_LEN)));
        recv_unprov_adv_pkt(param->provisioner_recv_unprov_adv_pkt.dev_uuid, param->provisioner_recv_unprov_adv_pkt.addr,
                            param->provisioner_recv_unprov_adv_pkt.addr_type, param->provisioner_recv_unprov_adv_pkt.oob_info,
                            param->provisioner_recv_unprov_adv_pkt.adv_type, param->provisioner_recv_unprov_adv_pkt.bearer);
        break;
    case ESP_BLE_MESH_PROVISIONER_PROV_LINK_OPEN_EVT:       //预配器建立BLE Mesh链接事件
        prov_link_open(param->provisioner_prov_link_open.bearer);
        break;
    case ESP_BLE_MESH_PROVISIONER_PROV_LINK_CLOSE_EVT:      //预配器关闭BLE Mesh链接事件
        ESP_LOGI(TAG,"ESP_BLE_MESH_PROVISIONER_PROV_LINK_CLOSE_EVT");
        prov_link_close(param->provisioner_prov_link_close.bearer, param->provisioner_prov_link_close.reason);
        break;
    case ESP_BLE_MESH_PROVISIONER_PROV_COMPLETE_EVT:        //预配器预配事件
        ESP_LOGI(TAG,"ESP_BLE_MESH_PROVISIONER_PROV_COMPLETE_EVT");
        prov_complete(param->provisioner_prov_complete.node_idx, param->provisioner_prov_complete.device_uuid,
                      param->provisioner_prov_complete.unicast_addr, param->provisioner_prov_complete.element_num,
                      param->provisioner_prov_complete.netkey_idx, node_mac);

        // xTaskCreate(send_msg,"send_msg",4096, param,7,NULL);

        break;
    case ESP_BLE_MESH_PROVISIONER_ADD_UNPROV_DEV_COMP_EVT:  //预配器将设备添加到列表，该列表包含等待/准备预配完成事件的设备
        ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_ADD_UNPROV_DEV_COMP_EVT, err_code %d", param->provisioner_add_unprov_dev_comp.err_code);
        break;
    case ESP_BLE_MESH_PROVISIONER_SET_DEV_UUID_MATCH_COMP_EVT://预配器设置要与未配置的设备UUID完成事件的一部分进行比较的值
        ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_SET_DEV_UUID_MATCH_COMP_EVT, err_code %d", param->provisioner_set_dev_uuid_match_comp.err_code);
        break;
    case ESP_BLE_MESH_PROVISIONER_SET_NODE_NAME_COMP_EVT: { //预配器设置节点名称完成事件
        ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_SET_NODE_NAME_COMP_EVT, err_code %d", param->provisioner_set_node_name_comp.err_code);
        if (param->provisioner_set_node_name_comp.err_code == ESP_OK) {
            const char *name = NULL;
            name = esp_ble_mesh_provisioner_get_node_name(param->provisioner_set_node_name_comp.node_index);
            if (!name) {
                ESP_LOGE(TAG, "Get node name failed");
                return;
            }
            ESP_LOGI(TAG, "Node %d name is: %s", param->provisioner_set_node_name_comp.node_index, name);
        }
        break;
    }
    case ESP_BLE_MESH_PROVISIONER_ADD_LOCAL_APP_KEY_COMP_EVT: { //预配器添加本地应用程序密钥完成事件
        ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_ADD_LOCAL_APP_KEY_COMP_EVT, err_code %d", param->provisioner_add_app_key_comp.err_code);
        if (param->provisioner_add_app_key_comp.err_code == ESP_OK) {
            esp_err_t err = 0;
            prov_key.app_idx = param->provisioner_add_app_key_comp.app_idx;
            // err = esp_ble_mesh_provisioner_bind_app_key_to_local_model(PROV_OWN_ADDR, prov_key.app_idx,
            //         ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_CLI, ESP_BLE_MESH_CID_NVAL);
            // if (err != ESP_OK) {
            //     ESP_LOGE(TAG, "Provisioner bind local model appkey failed");
            //     return;
            // }
            err = esp_ble_mesh_provisioner_bind_app_key_to_local_model(PROV_OWN_ADDR, prov_key.app_idx,
                    ESP_BLE_MESH_VND_MODEL_ID_CLIENT, CID_ESP);
            if (err != ESP_OK) {
                ESP_LOGE(TAG, "%s: Failed to bind AppKey with Fast Prov Client Model", __func__);
                return;
            }
        }
        break;
    }
    case ESP_BLE_MESH_PROVISIONER_BIND_APP_KEY_TO_MODEL_COMP_EVT:   //预配器将本地模型与本地应用程序密钥完成事件绑定
        ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_BIND_APP_KEY_TO_MODEL_COMP_EVT, err_code %d", param->provisioner_bind_app_key_to_model_comp.err_code);
        break;
    default:
        break;
    }

    return;
}

static void     example_ble_mesh_config_client_cb(esp_ble_mesh_cfg_client_cb_event_t event,
                                              esp_ble_mesh_cfg_client_cb_param_t *param)
{
    esp_ble_mesh_client_common_param_t common = {0};
    esp_ble_mesh_node_info_t *node = NULL;
    uint32_t opcode;
    uint16_t addr;
    int err;

    opcode = param->params->opcode;
    addr = param->params->ctx.addr;

    ESP_LOGI(TAG, "%s, error_code = 0x%02x, event = 0x%02x, addr: 0x%04x, opcode: 0x%04x",
             __func__, param->error_code, event, param->params->ctx.addr, opcode);

    if (param->error_code) {
        ESP_LOGE(TAG, "Send config client message failed, opcode 0x%04x", opcode);
        return;
    }

    node = example_ble_mesh_get_node_info(addr);
    if (!node) {
        ESP_LOGE(TAG, "%s: Get node info failed", __func__);
        return;
    }

    switch (event) {
    case ESP_BLE_MESH_CFG_CLIENT_GET_STATE_EVT:
        switch (opcode) {
        case ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET: {
            ESP_LOGI(TAG, "composition data %s", bt_hex(param->status_cb.comp_data_status.composition_data->data,
                     param->status_cb.comp_data_status.composition_data->len));
            esp_ble_mesh_cfg_client_set_state_t set_state = {0};
            example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD);
            set_state.app_key_add.net_idx = prov_key.net_idx;
            set_state.app_key_add.app_idx = prov_key.app_idx;
            memcpy(set_state.app_key_add.app_key, prov_key.app_key, 16);

            //将应用密钥添加到节点
            err = esp_ble_mesh_config_client_set_state(&common, &set_state);
            if (err) {
                ESP_LOGE(TAG, "%s: Config AppKey Add failed", __func__);
                return;
            }
            break;
        }
        default:
            break;
        }
        break;
    case ESP_BLE_MESH_CFG_CLIENT_SET_STATE_EVT:
        switch (opcode) {
        case ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD: {
            esp_ble_mesh_cfg_client_set_state_t set_state = {0};
            example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND);
            set_state.model_app_bind.element_addr = node->unicast;
            set_state.model_app_bind.model_app_idx = prov_key.app_idx;
            set_state.model_app_bind.model_id = ESP_BLE_MESH_VND_MODEL_ID_SERVER;
            set_state.model_app_bind.company_id = CID_ESP;
            //将应用密钥添加到节点
            err = esp_ble_mesh_config_client_set_state(&common, &set_state);
            if (err) {
                ESP_LOGE(TAG, "%s: Config Model App Bind failed", __func__);
                return;
            }
            break;
        }
        case ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND: {
            uint8_t my_addr[2] = {0}, my_opcode[3] = {0};
            my_addr[0] = addr >> 8; my_addr[1] = addr & 0xFF;
            my_opcode[0]= opcode >> 16; my_opcode[1] = opcode >> 8; my_opcode[2] = opcode & 0xFF;
            
            char json_buf[128] = {0};
            memset(json_buf,0,128);
            char bt_hex_Temp[32]={0};

            snprintf(json_buf,127,"{\"addr\":\"%s\",\"mac\":\"%s\"}",bt_hex(my_addr,sizeof(my_addr)), node->node_mac); 
            // memset(node_mac, 0, sizeof(node_mac));
            // printf("buf = %s\n",json_buf);
            my_mqtt_send(json_buf);

             ESP_LOGW(TAG, "%s, Provision and config successfully", __func__);
            break;
        }
        default:
            break;
        }
        break;
    case ESP_BLE_MESH_CFG_CLIENT_PUBLISH_EVT:
        switch (opcode) {
        case ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_STATUS:
            ESP_LOG_BUFFER_HEX("composition data %s", param->status_cb.comp_data_status.composition_data->data,
                               param->status_cb.comp_data_status.composition_data->len);
            break;
        case ESP_BLE_MESH_MODEL_OP_APP_KEY_STATUS:
            break;
        default:
            break;
        }
        break;
    case ESP_BLE_MESH_CFG_CLIENT_TIMEOUT_EVT:
        switch (opcode) {
        case ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET: {
            esp_ble_mesh_cfg_client_get_state_t get_state = {0};
            example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET);
            get_state.comp_data_get.page = COMP_DATA_PAGE_0;
            err = esp_ble_mesh_config_client_get_state(&common, &get_state);
            if (err) {
                ESP_LOGE(TAG, "%s: Config Composition Data Get failed", __func__);
                return;
            }
            break;
        }
        case ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD: {
            ESP_LOGE(TAG, "ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD");
            esp_ble_mesh_cfg_client_set_state_t set_state = {0};
            example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD);
            set_state.app_key_add.net_idx = prov_key.net_idx;
            set_state.app_key_add.app_idx = prov_key.app_idx;
            memcpy(set_state.app_key_add.app_key, prov_key.app_key, 16);

            //将应用密钥添加到节点
            err = esp_ble_mesh_config_client_set_state(&common, &set_state);
            if (err) {
                ESP_LOGE(TAG, "%s: Config AppKey Add failed", __func__);
                return;
            }
            break;
        }
        case ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND: {
            esp_ble_mesh_cfg_client_set_state_t set_state = {0};
            example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND);
            set_state.model_app_bind.element_addr = node->unicast;
            set_state.model_app_bind.model_app_idx = prov_key.app_idx;
            set_state.model_app_bind.model_id = ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV;
            set_state.model_app_bind.company_id = CID_ESP;
            //将应用密钥添加到节点
            err = esp_ble_mesh_config_client_set_state(&common, &set_state);
            if (err) {
                ESP_LOGE(TAG, "%s: Config Model App Bind failed", __func__);
                return;
            }
            break;
        }
        default:
            break;
        }
        break;
    default:
        ESP_LOGE(TAG, "Not a config client status message event");
        break;
    }
}


void ble_mesh_send_data(uint16_t addr, uint32_t parmOpcode, uint8_t *data, uint16_t length)
{    
    ESP_LOGI(TAG,"addr = %04x\tparmOpcode = %x\n",addr,parmOpcode);
    esp_ble_mesh_msg_ctx_t ctx = {0};    
    uint32_t opcode;
    ctx.net_idx = prov_key.net_idx;    
    ctx.app_idx = prov_key.app_idx;    
    ctx.addr = addr;    
    ctx.send_ttl = MSG_SEND_TTL;    
    ctx.send_rel = MSG_SEND_REL;    
    opcode = parmOpcode;    
    esp_err_t err = esp_ble_mesh_client_model_send_msg(&vnd_models[0], &ctx, opcode, length, data, MSG_TIMEOUT, false, MSG_ROLE);
    if (err) {        
        ESP_LOGE(TAG, "Failed to send message 0x%06x", ESP_BLE_MESH_VND_MODEL_OP_TEST_PERF_SET);    
    }
}

void ble_mesh_model_cb(esp_ble_mesh_model_cb_event_t event, esp_ble_mesh_model_cb_param_t *param)
{
    ESP_LOGI(TAG, "enter %s, event=%x\n", __func__, event);

    switch (event) {
    case ESP_BLE_MESH_MODEL_OPERATION_EVT:
        ESP_LOGI(TAG,"ESP_BLE_MESH_MODEL_OPERATION_EVT");
        break;
    case ESP_BLE_MESH_MODEL_SEND_COMP_EVT:
        ESP_LOGI(TAG,"ESP_BLE_MESH_MODEL_SEND_COMP_EVT");
        break;
    case ESP_BLE_MESH_MODEL_PUBLISH_COMP_EVT:
        ESP_LOGI(TAG,"ESP_BLE_MESH_MODEL_PUBLISH_COMP_EVT");
        break;
    case ESP_BLE_MESH_CLIENT_MODEL_RECV_PUBLISH_MSG_EVT:    //接收节点消息
        ESP_LOGI(TAG,"ESP_BLE_MESH_CLIENT_MODEL_RECV_PUBLISH_MSG_EVT");

        uint8_t addr[2] = {0}, opcode[3] = {0};
        addr[0] = param->client_recv_publish_msg.ctx->addr >> 8; addr[1] = param->client_recv_publish_msg.ctx->addr & 0xFF;
        opcode[0]= param->client_recv_publish_msg.opcode >> 16; opcode[1] = param->client_recv_publish_msg.opcode >> 8; opcode[2] = param->client_recv_publish_msg.opcode & 0xFF;
        char json_buf[128] = {0};
        memset(json_buf,0,128);
        char bt_hex_Temp[32]={0};
        memcpy(bt_hex_Temp,bt_hex(param->client_recv_publish_msg.msg, param->client_recv_publish_msg.length),strlen(bt_hex(param->client_recv_publish_msg.msg, param->client_recv_publish_msg.length)));
        //节点查询网关MAC操作
        if(strcmp(bt_hex(opcode,sizeof(opcode)),"d28888") == 0){
            if((strcmp(bt_hex_Temp,"4d41433f") == 0 )|| (strcmp(bt_hex_Temp, "4D41433F") == 0)){
                uint8_t mac[6];
                esp_read_mac(mac, ESP_MAC_WIFI_STA);
                ble_mesh_send_data(param->client_recv_publish_msg.ctx->addr, 
                                ESP_BLE_MESH_VND_MODEL_OP_TEST_PERF_STATUS, mac, 6);
                break;
            }
        }
        snprintf(json_buf,127,"{\"addr\":\"%s\",\"opcode\":\"%s\",\"data\":\"%s\"}",bt_hex(addr,sizeof(addr)),bt_hex(opcode,sizeof(opcode)),bt_hex_Temp);  
        my_mqtt_send(json_buf);
        
        break;
    case ESP_BLE_MESH_MODEL_PUBLISH_UPDATE_EVT:
        ESP_LOGI(TAG, "PublishUpdate,OK");
        break;
    case ESP_BLE_MESH_CLIENT_MODEL_SEND_TIMEOUT_EVT:
        ESP_LOGI(TAG, "Node:TimeOut");
        break;
    case ESP_BLE_MESH_MODEL_EVT_MAX:
        ESP_LOGI(TAG, "Node:MaxEvt");
        break;
    default:
        break;
    }

    ESP_LOGD(TAG, "exit %s\n", __func__);
}


static esp_err_t ble_mesh_init(void)
{
    uint8_t match[2] = {0x88, 0x88};
    esp_err_t err;

    // prov_key.net_idx = ESP_BLE_MESH_KEY_PRIMARY;
    // prov_key.app_idx = APP_KEY_IDX;

    // note_json note_json_p = {.app_key = "12"};
    // read_note_data(&note_json_p);
    // printf("appkey = %s\r\n", note_json_p.app_key);
    // uint8_t  app_key[16] = {0};
    // AsciiToHex(note_json_p.app_key, app_key,strlen(note_json_p.app_key));
    // memcpy(prov_key.app_key, app_key, 16);


    prov_key.net_idx = ESP_BLE_MESH_KEY_PRIMARY;
    prov_key.app_idx = APP_KEY_IDX;
    memset(prov_key.app_key, APP_KEY_OCTET, sizeof(prov_key.app_key));


    // memset(prov_key.app_key, APP_KEY_OCTET, sizeof(prov_key.app_key));
    // for(int i=0; i<sizeof(prov_key.app_key); i++)
    // {
    //     printf("appk_len = %02X\r\n", prov_key.app_key[i]);
    // }
    // //设置MTU大小
    // esp_ble_gatt_set_local_mtu(23);
    // printf("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",dev_uuid[0],dev_uuid[1],
    //     dev_uuid[2],dev_uuid[3],dev_uuid[4],dev_uuid[5],dev_uuid[6],dev_uuid[7],dev_uuid[8],dev_uuid[9],dev_uuid[10],
    //     dev_uuid[11],dev_uuid[12],dev_uuid[13],dev_uuid[14],dev_uuid[15]);
    //注册BLE MESH 配置回调
    esp_ble_mesh_register_prov_callback(example_ble_mesh_provisioning_cb);
    //注册BLE MESH 配置客户端回调
    esp_ble_mesh_register_config_client_callback(example_ble_mesh_config_client_cb);
    //// 注册BLE MESH　通用客户端回调
    // esp_ble_mesh_register_generic_client_callback(example_ble_mesh_generic_client_cb);

    err = esp_ble_mesh_register_custom_model_callback(ble_mesh_model_cb);
    if(err != ESP_OK)
        ESP_LOGE(TAG,"register error\n");

    err = esp_ble_mesh_init(&provision, &composition);
    if (err) {
        ESP_LOGE(TAG, "Initializing mesh failed (err %d)", err);
        return err;
    }

    err = esp_ble_mesh_client_model_init(&vnd_models[0]);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "esp_ble_mesh_client_model_init failed");
        return ESP_FAIL;
    }

   

    //设置UUID过滤器
    esp_ble_mesh_provisioner_set_dev_uuid_match(match, sizeof(match), 0x0, false);

    //扫描周围环境中未配置的设备
    esp_ble_mesh_provisioner_prov_enable(ESP_BLE_MESH_PROV_ADV | ESP_BLE_MESH_PROV_GATT);

    //设置和绑定Appkey
    if(NULL == esp_ble_mesh_provisioner_get_local_app_key(prov_key.net_idx, prov_key.app_idx)){
        esp_ble_mesh_provisioner_add_local_app_key(prov_key.app_key, prov_key.net_idx, prov_key.app_idx);
    }else {
        esp_ble_mesh_provisioner_update_local_app_key(prov_key.app_key, prov_key.net_idx, prov_key.app_idx);
    }
    
    ESP_LOGI(TAG, "BLE Mesh Provisioner initialized");

    return err;
}


/*************************************************
Function: 		HexToString
Description: 	hex字符数组转换成string字符串
Input: 			hex:原字符数组
                len:hex数组的长度
Output: 		str:输出的字符串              
Return: 		
*************************************************/
static void HexToString(char *str, uint8_t *hex, int nLen)
{
    char ddl,ddh;
    int i;

    for (i=0; i<nLen; i++)
    {
        ddh = 48 + hex[i] / 16;
        ddl = 48 + hex[i] % 16;
        if (ddh > 57) ddh = ddh + 7;
        if (ddl > 57) ddl = ddl + 7;
        str[i*2] = ddh;
        str[i*2+1] = ddl;
    }
    str[nLen*2] = '\0';
}

static int AsciiToHex(const char *pAscStr,uint8_t *pHexStr,int Len)
{
    int i = 0;
    int j = 0;
    if(Len % 2==0){
    }
    for(i=0;i<Len;i++)
    {

        if( ( pAscStr[i] >= '0' ) && ( pAscStr[i] <= '9' ) ){
            pHexStr[j] =  pAscStr[i] - '0';
        }
        else if( ( pAscStr[i] >= 'A' ) && ( pAscStr[i] <= 'F' ) ){
            pHexStr[j] = pAscStr[i] - '7';
        }
        else if( ( pAscStr[i] >= 'a' ) && ( pAscStr[i] <= 'f' ) ){
            pHexStr[j] = pAscStr[i] - 0x57;
        }
        else{
            pHexStr[j] = 0xff;
            return 0;
        }
        i++;
        if(i>=Len){
            return j+1;
        }
        if( ( pAscStr[i] >= '0' ) && ( pAscStr[i] <= '9' ) ){
            pHexStr[j] =pHexStr[j]*0x10+  pAscStr[i] - '0';
            // printf("%x\n",pHexStr[j]);
        }
        else if( ( pAscStr[i] >= 'A' ) && ( pAscStr[i] <= 'F' ) ){
            pHexStr[j] =pHexStr[j]*0x10+  pAscStr[i] - '7';
            // printf("%x\n",pHexStr[j]);
        }
        else if( ( pAscStr[i] >= 'a' ) && ( pAscStr[i] <= 'f' ) ){
            pHexStr[j] = pHexStr[j]*0x10+ pAscStr[i] - 0x57;
            // printf("%x\n",pHexStr[j]);
        }
        else{
            pHexStr[j] = 0xff;
            printf("%x\n",pHexStr[j]);
            return 0;
        }
        j++;
        
    }
    
    return j;
}//change by johhn

static void sendDataToBle(void *parm)
{
    mqtt_tranport_data mqtt_tranport_data_t;
    uint8_t data[32];
    uint8_t addr[2];
    uint8_t opcode[3];
    int data_len,i = 0;
    while(1){   
        if(xQueueReceive(mqtt_queue, &mqtt_tranport_data_t, 20 / portTICK_RATE_MS)){

            ESP_LOGI(TAG,"opcode:%s\taddr=%s\tdata:%s\n",mqtt_tranport_data_t.opcode,mqtt_tranport_data_t.addr,mqtt_tranport_data_t.data);  
            // //蓝牙传输以16进制,将字符串装为hex
            AsciiToHex(mqtt_tranport_data_t.opcode, opcode, strlen(mqtt_tranport_data_t.opcode));
            AsciiToHex(mqtt_tranport_data_t.addr, addr, strlen(mqtt_tranport_data_t.addr));
            data_len = AsciiToHex(mqtt_tranport_data_t.data, data, strlen(mqtt_tranport_data_t.data));
            for(i=0; i<data_len; i++){
                printf("data = %02x\n",data[i]);
            }
            //测试使用接口，确保删除节点信息以发出
            if(memcmp(mqtt_tranport_data_t.addr, "d28888", strlen("d28888"))){
                for(int i=0; i<3; i++){
                    ble_mesh_send_data((addr[0]<<8)|addr[1], (opcode[0]<<16)|(opcode[1]<<8)|opcode[2], data, data_len);
                }
                //删除节点信息
                if(ESP_OK != esp_ble_mesh_node_local_reset()){
                    ESP_LOGE(TAG, "Delete Note Info Failed");
                }
            }else{
                ble_mesh_send_data((addr[0]<<8)|addr[1], (opcode[0]<<16)|(opcode[1]<<8)|opcode[2], data, data_len);
            }
        }
    }
    vTaskDelete(NULL);
}


void my_ble_init(void)
{
    esp_err_t err;

    ESP_LOGI(TAG, "Initializing...");

    err = bluetooth_init();
    if (err) {
        ESP_LOGE(TAG, "esp32_bluetooth_init failed (err %d)", err);
        return;
    }

    ble_mesh_get_dev_uuid(dev_uuid);

    /* Initialize the Bluetooth Mesh Subsystem */
    err = ble_mesh_init();
    if (err) {
        ESP_LOGE(TAG, "Bluetooth mesh init failed (err %d)", err);
    }

    xTaskCreate(sendDataToBle,"sendDataToBle",4096,NULL,6,NULL);
}


